package com.weshare.nd.netty.server;

import com.weshare.nd.netty.coder.ChatDecode;
import com.weshare.nd.netty.coder.ChatEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.log4j.Logger;

public class ChatServer {
    private static final Logger logger = Logger.getLogger(ChatServer.class);

    private static final String IP = "127.0.0.1";
    private static final int PORT = 9999;

    /**
     * 用于分配处理业务线程的线程组个数
     */
    protected static final int ACCEPT_SIZE = 2; // 默认
    /**
     * 业务出现线程大小
     */
    protected static final int WORKER_SIZE = Runtime.getRuntime().availableProcessors() * 2;

    /**
     * NioEventLoopGroup实际上就是个线程池,
     * NioEventLoopGroup在后台启动了n个NioEventLoop来处理Channel事件,
     * 每一个NioEventLoop负责处理m个Channel,
     * NioEventLoopGroup从NioEventLoop数组里挨个取出NioEventLoop来处理Channel
     */
    private static final EventLoopGroup bossGroup = new NioEventLoopGroup(ACCEPT_SIZE);//acceptor
    private static final EventLoopGroup workerGroup = new NioEventLoopGroup(WORKER_SIZE);//worker I/O读写

    protected static void serverStart() throws Exception {
        ServerBootstrap boot = new ServerBootstrap();

        boot.group(bossGroup, workerGroup);
        boot.channel(NioServerSocketChannel.class);//注明服务端niochannel
        boot.option(ChannelOption.SO_BACKLOG, 100);//当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度
        boot.option(ChannelOption.TCP_NODELAY, true);
        boot.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast("chatDecoder", new ChatDecode());
                pipeline.addLast("chatEncoder", new ChatEncoder());
                pipeline.addLast("serverHandler", new ChatServerHandler());
            }
        });

        ChannelFuture serverChannel = boot.bind(PORT).sync();

        logger.info("聊天室已启动");

        serverChannel.channel().closeFuture().sync();

    }

    public static void shutdown() {
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }

    public static void main(String[] args) throws Exception {
        logger.info("开始启动TCP服务器...");
        serverStart();
    }
}
